package org.zjx.server;

import org.zjx.core.ClusterConfig;
import org.zjx.core.RemoteCommandInvoker;
import org.zjx.handler.CommandHandler;
import org.zjx.handler.CommandHandlerFactory;
import org.zjx.message.CommandMessage;
import org.zjx.message.ResponseMessage;

import java.net.InetSocketAddress;
import java.util.Optional;

/**
 * 集群命令处理器（主服务器核心组件）
 * 功能职责：
 * 1. 命令路由决策（本地/远程）
 * 2. 本地命令执行
 * 3. 远程命令转发
 * 4. 连接池管理
 * 5. 异常处理
 */
public class ClusterCommandProcessor {
    private final ClusterConfig clusterConfig;    // 集群配置
    private final RemoteCommandInvoker invoker;   // 远程调用器

    /**
     * 构造函数
     * @param clusterConfig 集群配置
     * @param invoker 远程命令调用器（带连接池）
     */
    public ClusterCommandProcessor(ClusterConfig clusterConfig,
                                   RemoteCommandInvoker invoker) {
        this.clusterConfig = clusterConfig;
        this.invoker = invoker;
    }

    /**
     * 处理入站命令
     * @param command 原始命令消息
     * @return 封装好的响应消息
     */
    public ResponseMessage processCommand(CommandMessage command) {
        // 1. 路由决策：确定目标节点
        final InetSocketAddress targetNode = determineTargetNode(command);

        // 2. 本地执行：当目标为主节点或未配置路由时
        if (isLocalExecution(targetNode)) {
            return executeLocally(command);
        }

        // 3. 远程转发：需要其他节点处理时
        return executeRemotely(command, targetNode);
    }

    /**
     * 路由决策逻辑
     */
    private InetSocketAddress determineTargetNode(CommandMessage command) {
        // 1. 优先从集群配置获取路由
        InetSocketAddress configuredNode = clusterConfig.getNodeForCommand(command.getCommand());

        // 2. 存在配置则使用配置节点，否则使用默认路由策略
        return configuredNode != null
                ? configuredNode
                : clusterConfig.getMasterAddress(); // 默认路由到主节点
    }

    /**
     * 判断是否需要本地执行
     */
    private boolean isLocalExecution(InetSocketAddress targetNode) {
        // 目标节点是主节点本身，或未配置路由时
        return targetNode.equals(clusterConfig.getMasterAddress());
    }

    /**
     * 本地命令执行
     */
    private ResponseMessage executeLocally(CommandMessage command) {
        // 1. 从工厂获取对应处理器
        Optional<CommandHandler> handler = CommandHandlerFactory.getHandler(command.getCommand());

        // 2. 存在处理器则执行，否则返回错误响应
        if (handler.isPresent()) {
            return handler.get().handle(command);
        }
        return buildErrorResponse(command, "未找到本地命令处理器: " + command.getCommand());
    }

    /**
     * 远程命令执行（使用连接池）
     *  熔断机制实现 修改后的远程调用逻辑
     */
    private ResponseMessage executeRemotely(CommandMessage command, InetSocketAddress targetNode) {
        return invoker.invokeRemote(command, targetNode);
    }

    /**
     * 构建错误响应消息
     */
    private ResponseMessage buildErrorResponse(CommandMessage cmd, String errorMsg) {
        return ResponseMessage.error(cmd, errorMsg);
    }
}